package com.tes;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.anddev.andengine.audio.music.Music;
import org.anddev.andengine.audio.music.MusicFactory;
import org.anddev.andengine.audio.sound.Sound;
import org.anddev.andengine.audio.sound.SoundFactory;
import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.ZoomCamera;
import org.anddev.andengine.engine.camera.hud.HUD;
import org.anddev.andengine.engine.camera.hud.controls.BaseOnScreenControl;
import org.anddev.andengine.engine.camera.hud.controls.BaseOnScreenControl.IOnScreenControlListener;
import org.anddev.andengine.engine.camera.hud.controls.DigitalOnScreenControl;
import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.engine.handler.physics.PhysicsHandler;
import org.anddev.andengine.engine.handler.timer.ITimerCallback;
import org.anddev.andengine.engine.handler.timer.TimerHandler;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXLayer;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXLoader;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXObject;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXObjectGroup;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXTiledMap;
import org.anddev.andengine.entity.layer.tiled.tmx.util.exception.TMXLoadException;
import org.anddev.andengine.entity.modifier.PathModifier;
import org.anddev.andengine.entity.modifier.PathModifier.Path;
import org.anddev.andengine.entity.primitive.Rectangle;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.background.ColorBackground;
import org.anddev.andengine.entity.scene.menu.MenuScene;
import org.anddev.andengine.entity.scene.menu.MenuScene.IOnMenuItemClickListener;
import org.anddev.andengine.entity.scene.menu.item.IMenuItem;
import org.anddev.andengine.entity.scene.menu.item.TextMenuItem;
import org.anddev.andengine.entity.scene.menu.item.decorator.ColorMenuItemDecorator;
import org.anddev.andengine.entity.sprite.AnimatedSprite;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.entity.text.ChangeableText;
import org.anddev.andengine.entity.text.Text;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.extension.input.touch.controller.MultiTouchController;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.font.Font;
import org.anddev.andengine.opengl.font.FontFactory;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
import org.anddev.andengine.ui.activity.BaseGameActivity;
import org.anddev.andengine.util.Debug;
import org.anddev.andengine.util.HorizontalAlign;
import com.tes.GameResource.PlayerDirection;
import com.tes.dao.HighScoreDAO;
import com.tes.model.HighScore;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;

public class TesGame3 extends BaseGameActivity implements
		IOnMenuItemClickListener {

	// SCREEN SIZE
	static final int CAMERA_WIDTH = 480;
	static final int CAMERA_HEIGHT = 320;

	// CAMERA
	private ZoomCamera mCamera;
	private HUD hud;

	// SCENE
	private Scene mainScene;
	private Scene loadScene;

	// MENU SCENE
	private MenuScene menuScene;

	static final int MENU_START = 100;
	static final int MENU_NEXT = 0;
	static final int MENU_LEVELS = MENU_NEXT + 1;
	static final int MENU_RESTART = MENU_START - 1;

	// TILEDMAP
	private TMXTiledMap mTMXTiledMap;

	// FONT
	// HIGHSCORE
	private BitmapTextureAtlas tFontHUD;
	private Font mFontHUD;

	// MENU
	private BitmapTextureAtlas tFontMenu;
	private Font mFontMenu;

	// LOADING
	private BitmapTextureAtlas tFontLoading;
	private Font mFontLoading;

	// HINT
	private BitmapTextureAtlas tFontHint;
	private Font mFontHint;

	// PLAYER
	private BitmapTextureAtlas tPlayer;
	private TiledTextureRegion mPlayer;

	// GHOST
	private BitmapTextureAtlas tGhost;
	private TiledTextureRegion mGhost;

	// PEOPLE
	private BitmapTextureAtlas tPeople;
	private TiledTextureRegion mPeople;

	// ITEM
	// TOILET PAPER
	private BitmapTextureAtlas tToiletPaper;
	private TextureRegion mToiletPaper;

	// BOST
	private BitmapTextureAtlas tBost;
	private TextureRegion mBost;

	// CONTROL
	private DigitalOnScreenControl playerControl;
	private IOnScreenControlListener controlListener;

	private BitmapTextureAtlas tControlBase;
	private TextureRegion mControlBase;

	private BitmapTextureAtlas tControlKnob;
	private TextureRegion mControlKnob;

	// DURATION OF PLAYER
	private long[] playerDuration = { 100, 100, 100 };

	private PlayerDirection playerDirection = PlayerDirection.NONE;

	// BASE SPEED
	private float baseVelocty = 40;
	// PLAYER SPEED
	private float playerVelocty = baseVelocty;
	// GHOST SPEED
	private float ghostVelocty = baseVelocty * 0.75f;
	// PEOPLE SPEED
	private float peopleVelocty = baseVelocty * 0.4f;

	// TIMER
	private TimerHandler timerHandler;
	private int time = GameResource.levelTime
			.get(GameResource.SelectedLevel - 1);
	private int remain;

	// SCORE
	private int score;

	// MUSIC AND SOUND
	// MUSIC
	private Music mMusic;
	// SOUND
	private Sound sTick;
	private Sound sHammer;
	private Sound sCuk;
	private Sound sWhoosh;

	// LOAD RESOURCE
	private boolean isMapLoad = false;
	private boolean isSceneLoad = false;
	private boolean isControlLoad = false;
	private boolean isResourceLoad = false;

	private boolean isBost = false;

	@Override
	public Engine onLoadEngine() {
		this.mCamera = GameResource.zoomCamera;

		final EngineOptions engineOptions = new EngineOptions(true,
				ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(
						CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera);
		engineOptions.setNeedsMusic(true);
		engineOptions.setNeedsSound(true);

		final Engine engine = new Engine(engineOptions);

		try {
			engine.setTouchController(new MultiTouchController());
		} catch (Exception e) {
			e.printStackTrace();
		}

		return engine;
	}

	@Override
	public void onLoadResources() {
		// SET PATH
		FontFactory.setAssetBasePath("font/");
		BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
		SoundFactory.setAssetBasePath("sound/");
		MusicFactory.setAssetBasePath("sound/");

		// SOUND
		try {
			sTick = SoundFactory.createSoundFromAsset(
					mEngine.getSoundManager(), this, "tick.wav");
			sHammer = SoundFactory.createSoundFromAsset(
					mEngine.getSoundManager(), this, "hammer.wav");
			sCuk = SoundFactory.createSoundFromAsset(mEngine.getSoundManager(),
					this, "cuk.wav");
			sWhoosh = SoundFactory.createSoundFromAsset(mEngine.getSoundManager(),
					this, "whoosh.wav");
			
			mMusic = MusicFactory.createMusicFromAsset(
					mEngine.getMusicManager(), this, "music.mp3");
			mMusic.setLooping(true);
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// FONT
		// menu
		tFontMenu = GameResource.tFontChiller;
		mFontMenu = GameResource.mFontChiller;
		// high score
		tFontHUD = GameResource.tFontQuartz;
		mFontHUD = GameResource.mFontQuartz;
		// loading
		tFontLoading = GameResource.tFontOCRAExt;
		mFontLoading = GameResource.mFontOCRAExt;
		// hint
		tFontHint = GameResource.tFontAllHookedUp;
		mFontHint = GameResource.mFontAllHookedUp;

		// character
		// player
		tPlayer = GameResource.tPlayer;
		mPlayer = GameResource.mPlayer;

		// ghost
		tGhost = GameResource.tGhost;
		mGhost = GameResource.mGhost;

		// ghost
		tPeople = GameResource.tPeople;
		mPeople = GameResource.mPeople;

		// toilet paper
		tToiletPaper = GameResource.tToiletPaper;
		mToiletPaper = GameResource.mToiletPaper;

		// bost
		tBost = GameResource.tBost;
		mBost = GameResource.mBost;

		// control
		// base
		tControlBase = GameResource.tControlBase;
		mControlBase = GameResource.mControlBase;
		// knob
		tControlKnob = GameResource.tControlKnob;
		mControlKnob = GameResource.mControlKnob;

		// load resource
		mEngine.getTextureManager().loadTextures(tFontMenu, tFontHUD,
				tFontLoading, tFontHint, tPlayer, tGhost, tPeople,
				tControlBase, tControlKnob, tToiletPaper, tBost);
		mEngine.getFontManager().loadFonts(mFontMenu, mFontHUD, mFontLoading,
				mFontHint);
	}

	@Override
	public Scene onLoadScene() {
		this.mEngine.registerUpdateHandler(new FPSLogger());

		loadScene = new Scene();

		final String stringLoad = "Loading Map";
		final ChangeableText loadingText = new ChangeableText(10,
				10 + mFontLoading.getLineHeight(), mFontLoading, stringLoad, 20);
		loadingText.setVisible(true);
		loadScene.attachChild(loadingText);

		loadScene.setBackground(new ColorBackground(1.0f, 1.0f, 1.0f));
		loadScene.registerUpdateHandler(new IUpdateHandler() {

			@Override
			public void reset() {
				// TODO Auto-generated method stub

			}

			@Override
			public void onUpdate(float pSecondsElapsed) {

				if (isResourceLoad) {
					loadScene.setChildScene(menuScene);
					loadingText.setVisible(false);
				} else {
					if (!isMapLoad) {
						mTMXTiledMap = loadMap(GameResource.levelTiledMap
								.get(GameResource.SelectedLevel - 1));
						loadingText.setText("Loading Scene");
						isMapLoad = true;
					} else if (!isSceneLoad) {
						mainScene = createMainScene();
						loadingText.setText("Loading Controller");
						isSceneLoad = true;
					} else if (!isControlLoad) {
						playerControl = createGameControl();
						isControlLoad = true;
					} else {
						isResourceLoad = true;
					}
				}

			}
		});

		// Saya ganti :)
		// menuScene = createMenuStart();
		menuScene = startGame();

		return loadScene;
	}

	@Override
	public void onLoadComplete() {
		mMusic.play();
	}

	@Override
	public boolean onMenuItemClicked(MenuScene pMenuScene, IMenuItem pMenuItem,
			float pMenuItemLocalX, float pMenuItemLocalY) {

		Intent intent;

		switch (pMenuItem.getID()) {
		case MENU_START:
			loadScene.clearChildScene();
			mCamera.setHUD(hud);
			mainScene.setChildScene(playerControl);
			mEngine.setScene(mainScene);

			score = 0;
			remain = time;
			break;

		case MENU_RESTART:
			intent = new Intent(this, TesGame3.class);
			startActivity(intent);

			this.finish();
			break;

		case MENU_LEVELS:
			this.finish();
			break;

		case MENU_NEXT:
			GameResource.SelectedLevel += 1;

			if (GameResource.SelectedLevel > GameResource.levelTiledMap.size()) {
				AlertDialog alertDialog = new AlertDialog.Builder(this)
						.create();
				alertDialog.setTitle("INFORMATION");
				alertDialog.setMessage("You Have Finish The Game");
				alertDialog.setButton(AlertDialog.BUTTON1, "OK",
						new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface arg0, int arg1) {
								TesGame3.this.finish();
							}
						});
				alertDialog.show();
			} else {
				intent = new Intent(this, TesGame3.class);
				startActivity(intent);

				this.finish();
			}
			break;
		default:
			break;
		}
		return false;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			AlertDialog.Builder alert = new AlertDialog.Builder(this);
			alert.setIcon(android.R.drawable.ic_dialog_alert);
			alert.setTitle("WARNING");
			alert.setMessage("Quit Level?");
			alert.setPositiveButton("Yes",
					new DialogInterface.OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {
							TesGame3.this.getEngine().getCamera().reset();
							TesGame3.this.finish();
						}

					});
			alert.setNegativeButton("No", null);
			alert.show();
			return true;
		}

		return super.onKeyDown(keyCode, event);
	}

	@Override
	public void finish() {
		if (hud != null)
			this.hud.setCamera(null);

		mCamera.setCenter(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2);
		super.finish();
	}

	// STARTING GAME :)
	protected MenuScene startGame() {
		MenuScene mScene = new MenuScene(this.mCamera);

		String hint = GameResource.levelHint
				.get(GameResource.SelectedLevel - 1);
		Text hintText = new Text(0, 0, mFontHint, hint);
		hintText.setPosition((CAMERA_WIDTH - hintText.getWidth()) / 2, 30);
		mScene.attachChild(hintText);

		IMenuItem startItem = new ColorMenuItemDecorator(new TextMenuItem(
				MENU_START, this.mFontMenu, "START"), 1.0f, 0.0f, 0.0f, 0.0f,
				0.0f, 1.0f);
		startItem.setPosition((CAMERA_WIDTH - startItem.getWidth()) / 2,
				CAMERA_HEIGHT - startItem.getHeight() - 20);
		mScene.addMenuItem(startItem);

		mScene.setBackgroundEnabled(false);
		mScene.setOnMenuItemClickListener(this);

		return mScene;
	}

	protected MenuScene createMenuFailed() {
		sCuk.play();
		MenuScene mScene = new MenuScene(this.mCamera);

		Text textScore = new Text(0, 10, mFontMenu, "Score : " + score);
		// Set Score pas ditengah-tengah layar :)
		textScore.setPosition(CAMERA_WIDTH / 3, 0);
		mScene.attachChild(textScore);

		IMenuItem startMenuItem = new ColorMenuItemDecorator(new TextMenuItem(
				MENU_RESTART, this.mFontMenu, "RESTART"), 1.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 1.0f);
		mScene.addMenuItem(startMenuItem);

		IMenuItem levelMenuItem = new ColorMenuItemDecorator(new TextMenuItem(
				MENU_LEVELS, this.mFontMenu, "LEVEL MENU"), 1.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 1.0f);
		mScene.addMenuItem(levelMenuItem);

		mScene.buildAnimations();
		mScene.setBackgroundEnabled(false);
		mScene.setOnMenuItemClickListener(this);

		return mScene;
	}

	protected MenuScene createMenuFinish() {
		MenuScene mScene = new MenuScene(this.mCamera);

		Text textScore = new Text(0, 10, mFontMenu, "Score : " + score);
		// Set Score pas ditengah-tengah layar :)
		textScore.setPosition(CAMERA_WIDTH / 3, 0);
		mScene.attachChild(textScore);

		IMenuItem nextMenuItem = new ColorMenuItemDecorator(new TextMenuItem(
				MENU_NEXT, this.mFontMenu, "NEXT"), 1.0f, 0.0f, 0.0f, 0.0f,
				0.0f, 1.0f);
		mScene.addMenuItem(nextMenuItem);

		IMenuItem levelMenuItem = new ColorMenuItemDecorator(new TextMenuItem(
				MENU_LEVELS, this.mFontMenu, "LEVEL MENU"), 1.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 1.0f);
		mScene.addMenuItem(levelMenuItem);

		mScene.buildAnimations();
		mScene.setBackgroundEnabled(false);
		mScene.setOnMenuItemClickListener(this);

		return mScene;
	}

	protected MenuScene createMenuStart() {
		MenuScene mScene = new MenuScene(this.mCamera);

		IMenuItem startMenuItem = new ColorMenuItemDecorator(new TextMenuItem(
				MENU_START, this.mFontMenu, "START"), 1.0f, 0.0f, 0.0f, 0.0f,
				0.0f, 1.0f);
		mScene.addMenuItem(startMenuItem);

		// Harusnya nggak usah aja...
		IMenuItem levelMenuItem = new ColorMenuItemDecorator(new TextMenuItem(
				MENU_LEVELS, this.mFontMenu, "SELECT LEVEL"), 1.0f, 0.0f, 0.0f,
				0.0f, 0.0f, 1.0f);
		mScene.addMenuItem(levelMenuItem);

		mScene.buildAnimations();
		mScene.setBackgroundEnabled(false);
		mScene.setOnMenuItemClickListener(this);

		return mScene;
	}

	protected DigitalOnScreenControl createGameControl() {
		DigitalOnScreenControl moveControl = new DigitalOnScreenControl(0 + 10,
				CAMERA_HEIGHT - this.mControlBase.getHeight() - 10,
				this.mCamera, this.mControlBase, this.mControlKnob, 0.01f,
				this.controlListener);

		// SET SCALE
		moveControl.getControlBase().setScale(1.1f);
		moveControl.getControlKnob().setScale(1.1f);

		// SET OPACITY
		moveControl.getControlBase().setAlpha(0.6f);
		moveControl.getControlKnob().setAlpha(0.5f);

		// REFRESH THE CONTROL KNOB POSITION
		moveControl.refreshControlKnobPosition();

		return moveControl;
	}

	protected TMXTiledMap loadMap(String file) {
		TMXTiledMap map = null;

		try {
			final TMXLoader tmxLoader = new TMXLoader(this,
					this.mEngine.getTextureManager(), TextureOptions.NEAREST);
			map = tmxLoader.loadFromAsset(this, file);
		} catch (final TMXLoadException tmxle) {
			Debug.e(tmxle);
			Log.d("Error Load Map", tmxle.getMessage());
		}

		return map;
	}

	protected Scene createMainScene() {
		final Scene scene = new Scene();

		// SET CAMERA BOUND
		final float tmxWidht = mTMXTiledMap.getTileColumns()
				* mTMXTiledMap.getTileWidth();
		final float tmxHeight = mTMXTiledMap.getTileRows()
				* mTMXTiledMap.getTileHeight();

		this.mCamera.setBounds(0, tmxWidht, -50, tmxHeight + 150);
		this.mCamera.setBoundsEnabled(true);

		// ADD TERAIN TO SCENE
		for (TMXLayer layer : mTMXTiledMap.getTMXLayers()) {
			if (layer.getTMXLayerProperties().containsTMXProperty("terrain",
					"true")) {
				scene.attachChild(layer);
			}
		}

		// GET OBJECT FROM TILED MAP
		final List<Rectangle> listUnpassObject = new ArrayList<Rectangle>();
		final List<Rectangle> listDieObject = new ArrayList<Rectangle>();
		final List<Rectangle> listGoolObject = new ArrayList<Rectangle>();
		final List<Rectangle> listItemObject = new ArrayList<Rectangle>();

		final List<Rectangle> listGhostObject = new ArrayList<Rectangle>();
		final List<Path> listGhostPath = new ArrayList<PathModifier.Path>();

		final List<Rectangle> listPeopleObject = new ArrayList<Rectangle>();
		final List<Path> listPeoplePath = new ArrayList<PathModifier.Path>();
		final Rectangle start = new Rectangle(0, 0, 0, 0);

		for (TMXObjectGroup objectGroup : this.mTMXTiledMap
				.getTMXObjectGroups()) {

			// ADD COLLIDE OBJECT
			if (objectGroup.getTMXObjectGroupProperties().containsTMXProperty(
					"collide", "true")) {
				for (TMXObject tmxObject : objectGroup.getTMXObjects()) {
					Rectangle rectangle = new Rectangle(tmxObject.getX(),
							tmxObject.getY(), tmxObject.getWidth(),
							tmxObject.getHeight());
					listUnpassObject.add(rectangle);
				}
			}

			// ADD COLLIDE OBJECT
			if (objectGroup.getTMXObjectGroupProperties().containsTMXProperty(
					"die", "true")) {
				for (TMXObject tmxObject : objectGroup.getTMXObjects()) {
					Rectangle rectangle = new Rectangle(tmxObject.getX(),
							tmxObject.getY(), tmxObject.getWidth(),
							tmxObject.getHeight());
					listDieObject.add(rectangle);
				}
			}

			// ADD ITEM OBJECT
			if (objectGroup.getTMXObjectGroupProperties().containsTMXProperty(
					"item", "true")) {
				for (TMXObject tmxObject : objectGroup.getTMXObjects()) {
					Rectangle rectangle = new Rectangle(tmxObject.getX(),
							tmxObject.getY(), tmxObject.getWidth(),
							tmxObject.getHeight());
					listItemObject.add(rectangle);
				}
			}

			// ADD GHOST OBJECT
			if (objectGroup.getTMXObjectGroupProperties().containsTMXProperty(
					"ghost", "true")) {
				Path path = new Path(objectGroup.getTMXObjects().size());

				for (TMXObject tmxObject : objectGroup.getTMXObjects()) {
					if (tmxObject.getTMXObjectProperties().containsTMXProperty(
							"move", "1")) {
						Rectangle rectangle = new Rectangle(tmxObject.getX(),
								tmxObject.getY(), tmxObject.getWidth(),
								tmxObject.getHeight());

						listGhostObject.add(rectangle);
					}

					path.to(tmxObject.getX(), tmxObject.getY());
				}

				listGhostPath.add(path);
			}

			// ADD PEOPLE OBJECT
			if (objectGroup.getTMXObjectGroupProperties().containsTMXProperty(
					"people", "true")) {
				Path path = new Path(objectGroup.getTMXObjects().size());

				for (TMXObject tmxObject : objectGroup.getTMXObjects()) {
					if (tmxObject.getTMXObjectProperties().containsTMXProperty(
							"move", "1")) {
						Rectangle rectangle = new Rectangle(tmxObject.getX(),
								tmxObject.getY(), tmxObject.getWidth(),
								tmxObject.getHeight());

						listPeopleObject.add(rectangle);
					}

					path.to(tmxObject.getX(), tmxObject.getY());
				}

				listPeoplePath.add(path);
			}

			// ADD GOOL OBJECT
			if (objectGroup.getTMXObjectGroupProperties().containsTMXProperty(
					"gool", "true")) {
				for (TMXObject tmxObject : objectGroup.getTMXObjects()) {
					Rectangle rectangle = new Rectangle(tmxObject.getX(),
							tmxObject.getY(), tmxObject.getWidth(),
							tmxObject.getHeight());
					listGoolObject.add(rectangle);
				}
			}

			// ADD START POSITION
			if (objectGroup.getTMXObjectGroupProperties().containsTMXProperty(
					"start", "true")) {
				for (TMXObject tmxObject : objectGroup.getTMXObjects()) {
					start.setPosition(tmxObject.getX(), tmxObject.getY());
				}
			}
		}

		// HUD
		hud = new HUD();

		// TIME
		final ChangeableText cRemainTime = new ChangeableText(
				CAMERA_WIDTH - 70, 5, mFontHUD, "----", HorizontalAlign.RIGHT,
				"----".length());

		hud.attachChild(cRemainTime);

		// SCORE : Mengganti nilai score ada di sini :)
		final ChangeableText cScore = new ChangeableText(10, 5, mFontHUD,
				"00000", HorizontalAlign.RIGHT, "00000".length());

		hud.attachChild(cScore);

		// BOST BUTTON
		final Sprite sBost = new Sprite(CAMERA_WIDTH - mBost.getWidth() - 50,
				CAMERA_HEIGHT - mBost.getHeight() - 25, mBost) {
			@Override
			public boolean onAreaTouched(final TouchEvent pSceneTouchEvent,
					final float pTouchAreaLocalX, final float pTouchAreaLocalY) {

				if (pSceneTouchEvent.isActionDown()) {
					sWhoosh.play();
					isBost = true;
				} else if (pSceneTouchEvent.isActionUp()) {
					isBost = false;
				}

				return true;
			}
		};
		hud.attachChild(sBost);
		hud.registerTouchArea(sBost);
		hud.setOnAreaTouchTraversalFrontToBack();
		hud.setTouchAreaBindingEnabled(true);

		// PLAYER
		final AnimatedSprite sPlayer = new AnimatedSprite(start.getX(),
				start.getY(), mPlayer);
		sPlayer.animate(playerDuration, 6, 8, true);

		// CREATE PHYSICSHANDLER FOR PLAYER
		final PhysicsHandler physicsPlayer = new PhysicsHandler(sPlayer);
		physicsPlayer.setVelocity(0, 0);
		sPlayer.registerUpdateHandler(physicsPlayer);

		scene.attachChild(sPlayer);
		// SET CAMERA TO CHASE PLAYER
		mCamera.setChaseEntity(sPlayer);

		// GHOST
		final List<AnimateObject> listGhostSprite = new ArrayList<AnimateObject>();

		for (int i = 0; i < listGhostObject.size(); i++) {
			Rectangle rect = listGhostObject.get(i);

			final AnimateObject sGhost = new AnimateObject(rect.getX(),
					rect.getY(), mGhost.deepCopy());
			sGhost.createPath(listGhostPath.get(i));
			sGhost.createPhysic(ghostVelocty);
			sGhost.createModifier();

			listGhostSprite.add(sGhost);

			scene.attachChild(sGhost);
		}

		// PEOPLE
		final List<AnimateObject> listPeopleSprite = new ArrayList<AnimateObject>();

		for (int i = 0; i < listPeopleObject.size(); i++) {
			Rectangle rect = listPeopleObject.get(i);

			final AnimateObject sPeople = new AnimateObject(rect.getX(),
					rect.getY(), mPeople.deepCopy());
			sPeople.createPath(listPeoplePath.get(i));
			sPeople.createPhysic(peopleVelocty);
			sPeople.createModifier();

			listPeopleSprite.add(sPeople);

			scene.attachChild(sPeople);
		}

		// ITEM
		// TOILET PAPER
		final List<Sprite> listItemSprite = new ArrayList<Sprite>();

		for (Rectangle rectangle : listItemObject) {
			final Sprite sItem = new Sprite(rectangle.getX(), rectangle.getY(),
					mToiletPaper.deepCopy());

			listItemSprite.add(sItem);
			scene.attachChild(sItem);
		}

		// ADD SURFACE FROM MAP
		for (TMXLayer layer : mTMXTiledMap.getTMXLayers()) {
			if (layer.getTMXLayerProperties().containsTMXProperty("object",
					"true")) {
				scene.attachChild(layer);
			}
		}

		// PLAYER CONTROL
		// LISTENER ON CONTROL CHANGE
		this.controlListener = new IOnScreenControlListener() {

			@Override
			public void onControlChange(
					BaseOnScreenControl pBaseOnScreenControl, float pValueX,
					float pValueY) {

				// CHECK MOVEMENT OF KNOB
				if (pValueY == 1) {
					// Up
					if (playerDirection != PlayerDirection.DOWN) {
						sPlayer.animate(playerDuration, 0, 2, true);
						playerDirection = PlayerDirection.DOWN;
					}
				} else if (pValueY == -1) {
					// Down
					if (playerDirection != PlayerDirection.UP) {
						sPlayer.animate(playerDuration, 9, 11, true);
						playerDirection = PlayerDirection.UP;
					}
				} else if (pValueX == -1) {
					// Left
					if (playerDirection != PlayerDirection.LEFT) {
						sPlayer.animate(playerDuration, 3, 5, true);
						playerDirection = PlayerDirection.LEFT;
					}
				} else if (pValueX == 1) {
					// Right
					if (playerDirection != PlayerDirection.RIGHT) {
						sPlayer.animate(playerDuration, 6, 8, true);
						playerDirection = PlayerDirection.RIGHT;
					}
				} else {
					if (sPlayer.isAnimationRunning()) {
						sPlayer.stopAnimation();
						playerDirection = PlayerDirection.NONE;
					}
				}

				float velocity = isBost ? playerVelocty * 3 : playerVelocty;
				// SET VELOCTY BASED ON KNOB MOVEMENT
				physicsPlayer.setVelocity(pValueX * velocity, pValueY
						* velocity);
			}
		};

		// timer handler
		timerHandler = new TimerHandler(1.0f, new ITimerCallback() {

			@Override
			public void onTimePassed(TimerHandler pTimerHandler) {

				String text = remain + "";
				for (int i = 0; i < 4 - text.length(); i++) {
					text = "0" + text;
				}

				cRemainTime.setText(text);

				if (remain < 20) {
					sTick.play();
				}

				if (remain <= 0) {
					menuScene = createMenuFailed();
					scene.setChildScene(menuScene, false, true, true);
				}

				if (remain > 0) {
					remain -= isBost ? 2 : 1;
					remain = remain < 0 ? 0 : remain;
					pTimerHandler.reset();
				}
			}
		});

		// scene update handler
		IUpdateHandler sceneHandler = new IUpdateHandler() {

			@Override
			public void reset() {

			}

			@Override
			public void onUpdate(float pSecondsElapsed) {
				// CHECK COLLIDE
				// FROM COLLIDE OBJECT
				for (Rectangle rectangle : listUnpassObject) {
					if (sPlayer.collidesWith(rectangle)) {
						physicsPlayer.setVelocity(
								-physicsPlayer.getVelocityX() * 5,
								-physicsPlayer.getVelocityY() * 5);
						break;
					}
				}

				// FROM GOOL
				for (Rectangle rectangle : listGoolObject) {
					if (sPlayer.collidesWith(rectangle)) {
						// Saya tambah +1 karena
						// waktu tidak presisi :)
						score += (remain + 1) * 10;
						menuScene = createMenuFinish();
						cScore.setText("00000");

						sPlayer.setInitialPosition();
						physicsPlayer.setVelocity(0, 0);

						HighScore hScore = new HighScoreDAO(
								getApplicationContext())
								.get(GameResource.SelectedLevel);

						if (hScore == null) {
							Toast.makeText(getApplicationContext(), "null",
									Toast.LENGTH_LONG).show();
						} else {
							if (hScore.getScore() < score) {
								hScore.setScore(score);
								new HighScoreDAO(getApplicationContext())
										.updateScore(hScore);
							}
						}

						scene.setChildScene(menuScene, false, true, true);

						for (Sprite sprite : listItemSprite) {
							if (!sprite.hasParent())
								scene.attachChild(sprite);
						}
					}
				}

				// FROM GHOST
				for (AnimatedSprite animatedSprite : listGhostSprite) {
					if (sPlayer.collidesWith(animatedSprite)) {
						// Tambahan dari saya :)
						sPlayer.stopAnimation();
						menuScene = createMenuFinish();
						scene.setChildScene(menuScene, false, true, true);
					}
				}

				// FROM PEOPLE
				playerVelocty = baseVelocty;
				for (AnimatedSprite animatedSprite : listPeopleSprite) {
					if (sPlayer.collidesWith(animatedSprite)) {
						playerVelocty = baseVelocty / 2;
					}
				}

				// FROM ITEM
				for (Sprite sprite : listItemSprite) {
					if (sprite.collidesWith(sPlayer)) {
						if (sprite.hasParent()) {
							sHammer.play();
							scene.detachChild(sprite);

							score += 10;
							String textScore = score + "";

							for (int i = 0; i < 4 - textScore.length(); i++) {
								textScore = "0" + textScore;
							}

							cScore.setText(textScore);
						}
					}
				}

				// CHECK IF PLAYER OUT FROM MAP
				// UP
				if (sPlayer.getY() < 0 && playerDirection == PlayerDirection.UP) {
					physicsPlayer.setVelocityY(-physicsPlayer.getVelocityY());
				}

				// LEFT
				if (sPlayer.getX() < 0
						&& playerDirection == PlayerDirection.LEFT) {
					physicsPlayer.setVelocityX(-physicsPlayer.getVelocityX());
				}

				// DOWN
				if (sPlayer.getY() > (tmxHeight - sPlayer.getHeight())
						&& playerDirection == PlayerDirection.DOWN) {
					physicsPlayer.setVelocityY(-physicsPlayer.getVelocityY());
				}

				// RIGHT
				if (sPlayer.getX() > (tmxWidht - sPlayer.getWidth())
						&& playerDirection == PlayerDirection.RIGHT) {
					physicsPlayer.setVelocityX(-physicsPlayer.getVelocityX());
				}

				// CHECK IF PLAYER ALREADY OUT FROM MAP OR IN IMPOSIBLE POSITION
				// X
				if (sPlayer.getX() <= -sPlayer.getWidth()
						|| sPlayer.getX() >= tmxWidht) {
					sPlayer.stopAnimation();
					menuScene = createMenuFailed();
					scene.setChildScene(menuScene, false, true, true);
				}
				// Y
				if (sPlayer.getY() <= -sPlayer.getHeight()
						|| sPlayer.getY() >= tmxHeight) {
					sPlayer.stopAnimation();
					menuScene = createMenuFailed();
					scene.setChildScene(menuScene, false, true, true);
				}
				// DIE AREA
				for (Rectangle rectangle : listDieObject) {
					if (sPlayer.collidesWith(rectangle)) {
						sPlayer.stopAnimation();
						menuScene = createMenuFailed();
						scene.setChildScene(menuScene, false, true, true);
					}
				}
			}
		};

		scene.registerUpdateHandler(timerHandler);
		scene.registerUpdateHandler(sceneHandler);

		return scene;
	}
}
